#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <net/if.h>
#include "udp_listen.h"
#include "liste.h"

#define PORT 6666
#define PORT_OUT 6667
#define MY_IP "192.168.1.1"
#define BUFFER_SIZE 5000

int tolower(int c) {
    if (c >= 'A' && c <= 'Z') 
        return c - 'A' + 'a';
    return c;
}

void itoa(int value, char string[4]) {
    int i=0;
    if (value < 0) {
        string[i] = '-';
        i++;
        value = -value;
    }
    string[i] = (value / 10) % 10 + '0';
    i++;
    string[i] = value % 10 + '0';
    i++;
    string[i] = '\0';
}

void local_mac_address(char local_ma[6]) {
    int s;
    struct ifreq buffer;
    s = socket(PF_INET, SOCK_DGRAM, 0);
    
    memset(&buffer, 0x00, sizeof(buffer));

    strcpy(buffer.ifr_name, "eth0");

    ioctl(s, SIOCGIFHWADDR, &buffer);

    close(s);

    for(s=0; s<6; s++) {
        local_ma[s] = (unsigned char) buffer.ifr_hwaddr.sa_data[s];
    }
}


void * listen_udp() {

    int skfd;
    struct sockaddr_in addr, remote_addr;
    char buffer[BUFFER_SIZE];
    size_t addr_size;
    u_char local_mac_addr[6];
    int average;
    char response[100];
    char rssi_str[4];

    local_mac_address(local_mac_addr);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    inet_pton(AF_INET, MY_IP, &addr.sin_addr);
    memset(&addr.sin_zero, '\0', 8);
    skfd = socket(PF_INET, SOCK_DGRAM, 0);
    if ( skfd == -1 ) {
        printf ( "Could not open skfd\n" );
    }
    if ( bind ( skfd, (struct sockaddr *) &addr,
                sizeof ( struct sockaddr ) ) == -1 ) {
        printf ( "Error when binding socket\n" );
    }


    while (1)
    if ( recvfrom ( skfd, buffer, BUFFER_SIZE - 1, 0,
                (struct sockaddr *) &remote_addr,
                &addr_size ) > 0 ) {
        int i;
        /* Use data from buffer
           (now remote_addr contains addr info on remote device) */
        //printf("received an udp packet\n");
        char delim[] = ";";
        printf("%s\n", buffer);
        if ( strncmp(buffer, "GET1;", 5) == 0 || strncmp(buffer, "GET0;", 5) == 0) {
            u_char mac_addr[6];
            char * result = NULL;
            int fin;

            strcpy(response, "RSSI;");

            if (strncmp(buffer, "GET0;", 5) == 0) {
                result = strtok(buffer, delim);
                result = strtok(NULL, delim);
                strcat(response, result);
                strcat(response, ";");
                result = strtok(NULL, delim);
                strcat(response, result);
                strcat(response, ";");
                result = strtok(NULL, delim);
                strcat(response, result);
                strcat(response, ";");
            }

            fin = strlen(response);

            for (i=0; i<6; i++) {
                char c[2];
                int j;
                for (j=0; j<2; j++) {
                    buffer[i*3+5+j] = tolower(buffer[i*3+fin+j]);
                    c[j] = (buffer[i*3+fin+j] >= 'a' ?
                            buffer[i*3+fin+j] - (int) 'a' + 10 :
                            buffer[i*3+fin+j] - (int) '0');
                }

                mac_addr[i] = (c[0] << 4) | c[1];
                response[i*3+fin] = buffer[i*3+fin];
                response[i*3+fin+1] = buffer[i*3+fin+1];
                response[i*3+fin+2] = ':';
            }

            response[fin + 17]=';';
            response[fin + 18]='\0';

            fin = strlen(response);
            
            /*for (i=0; i<18; i++) {
                response[i+fin] = local_mac_addr[i];
            }*/
            for (i=0; i<6; i++) {
                char c[2];
                int j;

                c[0] = local_mac_addr[i] & 0x0F;
                c[1] = (local_mac_addr[i] >> 4);

                for (j=0; j<2; j++) {
                    c[j] = (c[j]>9 ?
                            c[j]-10+'a' :
                            c[j] + '0');
                }
                response[i*3+fin] = c[1];
                response[i*3+fin+1] = c[0];
                response[i*3+fin+2] = ':';
            }
            response[fin+17] = ';';
            response[fin+18] = '\0';
            
            sem_wait(&list_protect);
            average = average_rssi(dl, mac_addr);
            sem_post(&list_protect);

            itoa(average, rssi_str);
            strcat(response, rssi_str);

            printf("%s\n", response);

            remote_addr.sin_port = htons(PORT_OUT);

            if (sendto(skfd, response, strlen(response), 0, 
                        (struct sockaddr *) &remote_addr,
                        addr_size) < 0) {
                printf("error: Could not send data to the server.\n");
            }
        }
        for (i=0; i<BUFFER_SIZE; i++) {
            buffer[i] = '\0';
        }
    }


    close ( skfd );
}
